﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;


namespace Neuron.Cell
{
    public delegate void DelegateActionEvent(double status);

    class DelayBuffer
    {
        private class BufferItem
        {
            private double _status = 0.0;
            private TimeSpan _delay = TimeSpan.MinValue;

            public BufferItem(double status, TimeSpan delayInMilliseconds)
            {
                this._status = status;
                this._delay = delayInMilliseconds;
            }

            public double Status
            {
                get {return this._status; }
            }

            public TimeSpan Delay
            {
                get {return this._delay; }
                set { this._delay = value; }
            }

        }
        
        List<BufferItem> _buffer = null;
        DateTime _firstEvent = DateTime.MinValue;
        DateTime _lastTrigger = DateTime.MinValue;
        int _startDelay = 0;
        Thread _thread = null;
        bool _running = false;

        public event DelegateActionEvent ActionEvent;
        
        public DelayBuffer(int delayInMilliseconds)
        {
            this._buffer = new List<BufferItem>();
            this._thread = null;
            this._startDelay = delayInMilliseconds;
        }

        public void Start()
        {
            this._running = true;
            this._thread = new Thread(this.processBuffer);
            this._thread.Start();
            while (!this._thread.IsAlive) ;
        }

        public void Stop()
        {
            this._running = false;
            if (this._thread != null)
            {
                while (this._thread.IsAlive) ;
                this._thread.Abort();
                this._thread = null;
            }
        }


        public void Add(double status)
        {
            TimeSpan deltaTime = TimeSpan.MinValue;

            // Neues Buffer-Item wird erstellt
            BufferItem bi = new BufferItem(status, TimeSpan.MaxValue);
            if (this._buffer.Count > 0)
            {
                // Die Zeitspanne des alten items wird neu berechnet
                BufferItem oldBi = this._buffer[this._buffer.Count - 1];
                oldBi.Delay = DateTime.Now - this._lastTrigger;
            }

            // element muss immer zum Buffer hinzugefügt werden
            this._buffer.Add(bi);
            this._lastTrigger = DateTime.Now;
        }
/*


        public void Add(double status)
        {
            TimeSpan deltaTime = TimeSpan.MinValue;

            if (this._firstEvent == DateTime.MinValue)
            {
                this._firstEvent = DateTime.Now;
                deltaTime = (DateTime.Now - this._firstEvent);
            }
            else
            {
                deltaTime = (DateTime.Now - this._lastTrigger);
            }

            BufferItem tmpBufferItem = new BufferItem(status, deltaTime);
            this._buffer.Add(tmpBufferItem);

            this._lastTrigger = DateTime.Now;
        }
*/
        public void processBuffer()
        {
            while (this._running)
            {
                if ((this._buffer.Count > 0)&&(this._running == true))
                {
                    Thread.Sleep(this._startDelay);

                    while (this._buffer.Count > 0)
                    {
                        BufferItem tmpItem = this._buffer[0];
                        if (this.ActionEvent != null)
                        {
                            ActionEvent(tmpItem.Status);
                        }
                        if (this._buffer.Count > 1)
                        {
                            Thread.Sleep(tmpItem.Delay);
                        }
                        this._buffer.Remove(tmpItem);
                    }

                    this._firstEvent = DateTime.MinValue;
                }
            }
        }

    }
}
